<?php

namespace common\components\fs;

use common\components\image_beds\EasyImageFs;
use common\components\image_beds\wbed\WbedFs;
use common\components\wtools\tools\FileHelper;
use common\components\wtools\tools\Model;
use common\components\wtools\tools\Tools;
use common\models\db\Files;
use yii\base\Component;

/**
 * @property Files|null $file
 * @property string $abUrl
 */
abstract class Fs extends Component implements FsApi
{
    /**
     * @param $id
     * @return mixed
     * @throws \Exception
     */
    public static function getComponentById($id)
    {
        $map = [
            LocalFs::getComponentId() => new LocalFs(),
            EasyImageFs::getComponentId() => new EasyImageFs(),
            WbedFs::getComponentId() => new WbedFs(),
        ];
        if (!isset($map[$id])) {
            throw new \Exception("文件系统不存在：".$id);
        }
        return $map[$id];
    }

    /** @var Files|null */
    private $_file;

    public function setFile(Files $file)
    {
        $this->_file = $file;
    }

    public function getFile()
    {
        return $this->_file;
    }

    /**
     * @param string $base64 标准base64格式
     * @param string|null $filename
     * @return Files|null
     * @throws \yii\base\Exception
     */
    public function uploadByBase64(string $base64, string $filename = null)
    {
        $base64Arr = explode(';', $base64);
        if (count($base64Arr) < 2) {
            if (!$filename) {
                throw new \Exception("请指定文件名filename");
            }
            $base64Data = $base64;
            $mimeType = 'application/unknown';
        } else {
            list($header, $base64Data) = explode(',', $base64);
            $tmpStr = str_replace('data:', '', $header);
            $mimeType = str_replace(';base64', '', $tmpStr);
        }
        if ($filename) {
            $ext = FileHelper::getExt($filename);
        } else {
            $ext = \Yii::$app->wMimeTypes->getExtension($mimeType);
        }
        $base64Content = base64_decode($base64Data);
        $md5 = md5($base64Content);
        $size = strlen($base64Content);
        $searchIndex = $md5.".".$size;
        $idFileName = $searchIndex.".".$ext;
        $file = Files::find()->andWhere(['like', 'filename', $searchIndex.'%', false])->one();
        if ($file) {
            $this->file = $file;
            return $this->file;
        } else {
            $url = $this->uploadBase64($idFileName, $base64);
            $this->file = new Files();
            $this->file->fs_component_id = static::getComponentId();
            switch (substr($mimeType, 0, 5)) {
                case 'image':
                    $this->file->type = $this->file::TYPE_1;
                    break;
                case 'video':
                    $this->file->type = $this->file::TYPE_2;
                    break;
                default:
                    $this->file->type = $this->file::TYPE_99;
                    break;
            }
            $this->file->filename = $idFileName;
            return $this->saveFile($url);
        }
    }

    public function getIndex()
    {
        if (!$this->file) {
            throw new \Exception("文件不存在");
        }
        list($md5, $size, $ext) = explode('.', $this->file->filename);
        return $md5.".".$size;
    }

    public function getSize()
    {
        if (!$this->file) {
            throw new \Exception("文件不存在");
        }
        list($md5, $size, $ext) = explode('.', $this->file->filename);
        return $size;
    }

    public function getExt()
    {
        if (!$this->file) {
            throw new \Exception("文件不存在");
        }
        list($md5, $size, $ext) = explode('.', $this->file->filename);
        return $ext;
    }
}
